home *** CD-ROM | disk | FTP | other *** search
- *cN Curso de programación orientada a objetos (II)
- *cG
- En el anterior articulo nos quedamos a punto de ver que era la sobrecarga
- despues de dar nuestros primeros pasos en la filosofia de la OOP. Recordad
- los conceptos tratados pues será fundamental para poder seguir este y los
- siguientes artículos.
- La sobrecarga es una potente técnica usada en los lenguajes POO para evitar
- los feos códigos fuente que se generan en los lenguajes tradicionales.
- Básicamente consiste en poder tener varias funciones con el mismo nombre
- dentro de un mismo programa. ¿Recordais en C cuando habia que usar nombres
- de funciones como *cOint_a_float()*cG, *cOstring_a_float()*cG, etc para convertir de
- un formato de datos a otro? Si lo que queremos es simplemente convertir de un
- tipo de dato dado a un float, ¿no seria más normal usar una función llamada
- *cOa_float()*cG para hacerlo?
- C++ soluciona este problema con la sobrecarga y añade a esta filosofia un
- nuevo concepto que a mi personalmente me gusta mucho: la sobrecarga de
- operadores. Este concepto significa que eso mismo que hacemos con las funciones
- lo podemos hacer con los operadores (+, -, /, !, etc) y así podemos crear una
- clase para manejar números complejos y sobrecargar el operador de suma "+" y
- poder así sumar dos numeros complejos de la forma más natural que podriamos
- imaginar.
- C++ como ya todos sabreis es un super-conjunto de C y por lo tanto se puede
- programar en C++ tal y como programariamos en C. Pero no se debe hacer ya que
- si lo hacemos perdemos todo lo que ganamos con la POO. Por tanto, si durante
- la série de artículos estais haciendo un programa y no sabeis como hacer algo
- en C++ podeis usar el C tradicional y luego pasarlo a C++ cuando sepais más.
- Para definir una clase en C++ se suelen usar 2 ficheros (y es muy conveniente
- hacerlo): uno para definir la clase y otra con los métodos (funciones) que
- usará esa clase. Para definir la clase se puede hacer así:
- *cB
- class nombre { [ 1]
- private: [ 2]
- dato_a_1; [ 3]
- ... [ 4]
- dato_a_n; [ 5]
- protected: [ 6]
- dato_b_1; [ 7]
- ... [ 8]
- dato_b_n; [ 9]
- public: [10]
- dato_c_1; [11]
- ... [12]
- dato_c_n; [13]
- }; [14]
- *cG
- Primero (linea 1) ponemos nombre a la clase que vamos a definir y abrimos
- la llave que definirá la zona de definición de la clase. Podemos ver en las
- líneas 2, 6 y 10 las palabras clave *cOprotected*cG, *cOprivate*cG y *cOpublic*cG que
- definen por quien podrán ser 'vistos' los distintos miembros de la clase. Los
- miembros protected no podran modificarse ni utilizarse desde fuera de los
- miembros de la clase. Private es la opción por defecto, es decir, si metemos
- algún miembro justo después de escribir la llave de apertura este pertenecerá
- al tipo private. Por otra parte, los tipos private y protected sólo se
- diferencian cuando se heredan clases así que ya los veremos cuando veamos este
- tópico. El tipo public define los miembros visibles desde cualquier lugar de
- la aplicación.
- En las líneas donde he escrito *cEdato_?_?*cG podriamos haber definido tanto un
- dato como un método (así se llaman las funciones en los lenguajes de OOP).
- Para que la cosa quede más clara ahí va la definición de una pequeña clase
- llamada *cEhormiga*cG que bien podria pertenecer a una aplicación de vida
- artificial:
- *cB
- class Hormiga { [ 1]
- private: [ 2]
- int posicionX; [ 3]
- int posicionY; [ 4]
- int reserva; [ 5]
- public: [ 6]
- void avanza(void); [ 7]
- void avanza(int x, int y); [ 8]
- void come(void); [ 9]
- void refresca(void); [10]
- }; [11]
- *cG
- En el ejemplo se ven cosas bastantes interesantes. En la primera línea vemos
- el nombre de la clase y hay que hacer notar que es muy importante recordar que
- tanto C como C++ son *cOcase sensitive*cG, es decir, que no es lo mismo *cEHormiga*cG
- que *cEhormiga*cG. En la parte private hemos metido las variables y NO en la parte
- public, nunca en la parte public ya que en la POO no debemos ordenar las cosas
- sino "pedirlas" (ver artículo anterior). Podemos ver también una sobrecarga de
- funciones (líneas 7 y 8) así cuando usemos un objeto de la clase *cEHormiga*cG
- podremos escribir tanto *cOavanza();*cG como *cOavanza(1,-1);*cG siendo esto mucho más
- intuitivo de cara al programador.
- Esta clase deberia ser "implementada" en otro fichero aunque hay gente que
- le tiene el mal habito de implementarla en el mismo fichero de definición
- (hay programadores que incluso lo meten todo en el main). Implementar la clase
- no es más que escribir el código de los métodos definidos e inicializar las
- variables de la clase. Las extensiones que se suelen usar para los ficheros
- de definición o cabecera son HPP o HH y para los de implementación CPP.
- Los métodos se definen escribiendo el tipo de datos que devuelven, el nombre
- de la clase, 4 puntos :-) es decir un doble dos puntos (::), el nombre del
- método que vamos a definir y los parámetros de entrada. Como ejemplo vamos a
- definir los 4 métodos de la clase Hormiga:
- *cB
- void Hormiga :: avanza(void) [ 1]
- { [ 2]
- posicionX += random(2); [ 3]
- posicionY += random(2); [ 4]
- } [ 5]
- [ 6]
- void Hormiga :: avanza(int x, int y) [ 7]
- { [ 8]
- posicionX += x; [ 9]
- posicionY += y; [10]
- } [11]
- [12]
- void Hormiga :: come(void) [13]
- { [14]
- if(campo.hay_comida(posicionX, posicionY)) [15]
- reserva += campo.come(posicionX, posicionY); [16]
- } [17]
- [18]
- void Hormiga :: refresca(void) [19]
- { [20]
- if(--reserva < 0) [21]
- printf("La hormiga se ha muerto de hambre"); [22]
- campo.dibuja(this); [23]
- } [24]
- *cG
- En este ejemplo hay mucho trigo que trillar... Para empezar en las líneas
- 1, 7, 13 y 19 podemos ver lo que estaba explicando antes de la definición de
- los métodos: *cOvoid clase :: metodo(dato_1, ..., dato_n)*cG. Observa lo simple
- que ha sido definir dos métodos distintos para hacer lo mismo y con el mismo
- nombre (líneas 1-5 y 7-11) aprovechando la potencia de la sobrecarga. Las dos
- primeras funciones simplemente actualizan un par de variables internas, NO
- modificables desde fuera de la clase Hormiga.
- La función come (13-17) comprueba si en la parte del campo donde está situada
- hay algo para comerselo y si es así se lo come. Aquí hay un punto (y nunca
- mejor dicho) bastante importante que debemos abordar. Seguro que te ha
- resultado extraño el nombre de la función *cOcampo.hay_comida()*cG y la de comer
- *cOcampo.come()*cG. No se trata de un nuevo modo de nombrar los métodos en C++,
- sino que es la llamada a un método de un objeto. En efecto, cuando nosotros
- creamos una clase y un objeto de esa clase, para llamar a los métodos de la
- zona pública del objeto (de la clase) debemos usar el nombre del objeto (del
- objeto que no de la clase), un punto y el método que vamos a llamar (este
- proceso lo desarrollaremos en profundidad más adelante). Para entender mejor
- todo esto, vamos a definir un par de objetos Hormiga y vamos a usarlos:
- *cB
- Hormiga Pepa;
- Hormiga Clara, Sofia;
-
- Pepa.avanza();
- Clara.come();
- *cG
- Supongo que queda claro como se definen objetos y se usan. No entraré en más
- detalles, simplemente debo hacer notar que aunque parezca que las clases no
- son más que estructuras de datos y funciones (bastante parecidas a las de C),
- esto no es cierto ya que las clases son algo más que ya iremos viendo.
- Un pequeño punto negro que queda por explicar en el código es el extraño
- "this" que aparece en la línea 23. Simplemente se trata de un puntero que se
- define automáticamente al crear un objeto y que apunta a él mismo. Por cierto,
- hay un elemento que no corresponde al C++ y es esa llamada a *cOprintf()*cG que
- queda obsoleta con los nuevos mecanismo de la POO que explicaremos más
- adelante.
- Con este interesante ejemplo abordado hoy ya se está capacitado para
- plantearse problemas más complejos como el de la heréncia, los métodos inline
- y los constructores y destructores que veremos en el próximo número junto a
- un tema no muy relacionado con la POO, pero muy interesante para los
- programadores en C++ que es la compilación separada y el uso de las directivas
- del compilador para crear un código más elegante.
- *cL
- Navi Dj.
-
-